﻿using System;
using System. Linq;
using System. Collections. Generic;
using System. IO. IsolatedStorage;
using NextApp. WP7. Models;
using System. Net;
using System. Xml. Linq;
using NextApp. WP7. Cache. Base;

namespace NextApp. WP7. Cache. NextApp
{
	public class CacheNextApp : CacheBase
	{
		#region Singleton
		private static readonly CacheNextApp instance = new CacheNextApp( );
		public static CacheNextApp Instance { get { return instance; } }
		private CacheNextApp( ) { }
		#endregion

		#region 文章详情列表 读写
		/// <summary>
		/// 存储文章到缓存
		/// </summary>
		/// <param name="post">文章详情</param>
		public void SavePostDetailToCache(Post post)
		{
			Dictionary<int, Post> postsDetail;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Dictionary<int, Post>>("Cache_PostsDetail", out postsDetail);
			if ( postsDetail != null )
			{
				postsDetail[ post. id ] = post;
			}
			else
			{
				postsDetail = new Dictionary<int, Post>( );
				postsDetail. Add(post. id, post);
			}
			IsolatedStorageSettings. ApplicationSettings[ "Cache_PostsDetail" ] = postsDetail;
			IsolatedStorageSettings. ApplicationSettings. Save( );
		}

		/// <summary>
		/// 从缓存中获取文章详情
		/// </summary>
		/// <param name="postID">文章ID</param>
		/// <returns>返回的文章详情</returns>
		public Post GetPostDetailFromCache(int postID)
		{
			Dictionary<int, Post> postsDetail;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Dictionary<int, Post>>("Cache_PostsDetail", out postsDetail);
			if ( postsDetail != null )
			{
				return postsDetail. ContainsKey(postID) ? postsDetail[ postID ] : null;
			}
			else
				return null;
		}
		#endregion

		#region 文章列表 读写
		/// <summary>
		/// 存储文章粗略信息到缓存
		/// </summary>
		/// <param name="posts">文章粗略信息列表</param>
		public void SavePostListToCache(IEnumerable<Post> posts)
		{
			if ( posts == null || posts. Count( ) == 0 )
			{
				return;
			}
			Post[ ] postsCache;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Post[ ]>("Cache_Posts", out postsCache);
			if ( postsCache != null )
			{
				postsCache = postsCache. Union(posts, new Util. PostCompare( )). ToArray( );
			}
			else
			{
				postsCache = posts. ToArray( );
			}
			IsolatedStorageSettings. ApplicationSettings[ "Cache_Posts" ] = postsCache;
			IsolatedStorageSettings. ApplicationSettings. Save( );
		}
		/// <summary>
		/// 从缓存读取文章列表粗略信息
		/// </summary>
		/// <param name="catalogID">文章分类信息</param>
		/// <param name="fromPostID">上一次获取文章的最后ID</param>
		/// <param name="fetchCount">拉取元素数目</param>
		/// <param name="isSortDesc">是否为逆向排序</param>
		/// <returns>读取的文章列表粗略信息</returns>
		public Post[ ]  GetPostListFromCache(int catalogID, int fromPostID, int fetchCount, bool isSortDesc=true)
		{
			Post[ ] postsCache;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Post[ ]>("Cache_Posts", out postsCache);
			if ( postsCache == null )
			{
				return null;
			}
			else
			{
				//文章分类处理
				if ( catalogID != 0 )
				{
					postsCache = postsCache. Where(p => p. catalog. Contains(catalogID)). ToArray( );
				}
				//排序处理
				postsCache = isSortDesc ? postsCache. OrderByDescending(p => p. id). ToArray( ) : postsCache. OrderBy(p => p. id). ToArray( );
				//返回结果
				if ( fromPostID <= 0 )
				{
					return postsCache. Take(fetchCount). ToArray( );
				}
				else
				{
					return isSortDesc ?
						postsCache. Where(p => p. id < fromPostID). Take(fetchCount). ToArray( ) :
						postsCache. Where(p => p. id > fromPostID). Take(fetchCount). ToArray( );
				}
			}
		}
		#endregion

		#region 评论列表 读写
		/// <summary>
		/// 存储评论信息到缓存
		/// </summary>
		/// <param name="comments">评论信息列表</param>
		public void SaveCommentsToCache(IEnumerable<Comment> comments)
		{
			if ( comments == null || comments. Count( ) == 0 )
			{
				return;
			}
			Comment[ ] commentsCache;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Comment[ ]>("Cache_Comments", out commentsCache);
			if ( commentsCache != null )
			{
				commentsCache = commentsCache. Union(comments, new Util. CommentCompare( )). ToArray( );
			}
			else
			{
				commentsCache = comments. ToArray( );
			}
			IsolatedStorageSettings. ApplicationSettings[ "Cache_Comments" ] = commentsCache;
			IsolatedStorageSettings. ApplicationSettings. Save( );
		}

		/// <summary>
		/// 从缓存读取文章列表粗略信息
		/// </summary>
		/// <param name="postID">对应文章ID</param>
		/// <param name="fromCommentID">上一次获取评论的最后ID</param>
		/// <param name="fetchCount">拉取元素数目</param>
		/// <param name="isSortDesc">是否为逆向排序</param>
		/// <returns>读取的文章列表粗略信息</returns>
		public Comment[ ] GetCommentListFromCache(int postID, int fromCommentID, int fetchCount, bool isSortDesc)
		{
			Comment[ ] commentsCache;
			IsolatedStorageSettings. ApplicationSettings. TryGetValue<Comment[ ]>("Cache_Comments", out commentsCache);
			if ( commentsCache == null )
			{
				return null;
			}
			else
			{
				//评论分类处理 如果仅仅只与一篇文章有关
				if ( postID != 0 )
				{
					commentsCache = commentsCache. Where(c => c. post == postID). ToArray( );
				}
				//排序处理
				commentsCache = isSortDesc ? commentsCache. OrderByDescending(c => c. id).ToArray( ) : commentsCache. OrderBy(c => c. id).ToArray( );
				//如果仅仅来自于一篇文章
				if ( postID == 0 )
				{
					return fromCommentID > 0 ?
						commentsCache. Where(c => c. id < fromCommentID). Take(fetchCount). ToArray( ) :
						commentsCache. Take(fetchCount). ToArray( );
				}
					//如果是全局评论获取的话 那么一定是逆向排序 
				else
				{
					return fromCommentID > 0 ?
						commentsCache. Where(c => c. id > fromCommentID). Take(fetchCount). ToArray( ) :
						commentsCache. Take(fetchCount). ToArray( );
				}
			}
		}
		#endregion

		public string userAgent { get; set; }
		protected override void ProcessThisMission(AsyncMissionBase mission)
		{
			WebClient client = new WebClient( );
			client. Headers[ "User-Agent" ] = userAgent;
			client. DownloadStringCompleted += (s, e) =>
				{
					if ( (mission as AsyncMissionNextApp).Type == AsyncMissionNextAppType.Post_Detail )
					{
						System. Diagnostics. Debug. WriteLine(e. Result);
					}

					//收回带宽消耗
					if ( e. Error != null )
					{
						System. Diagnostics. Debug. WriteLine("缓存任务处理出现错误: {0}", e. Error. Message);
						return;
					}
					XElement nextapp;
					try
					{
						nextapp = XElement. Parse(e. Result);
						if ( nextapp == null )
						{
							return;
						}
					}
					catch ( Exception ex)
					{
						System. Diagnostics. Debug. WriteLine("后台线程异步获取结果后出错: {0}  \r\n带宽消耗: {1}  \r\n错误结果: {2}", ex. Message, ( mission as AsyncMissionNextApp ). Type, e. Result);
						return;
					}
					if ( nextapp != null )
					{
						switch ( (mission as AsyncMissionNextApp).Type )
						{
							case AsyncMissionNextAppType. None:
								break;
							case AsyncMissionNextAppType. Post_Detail:
								ProcessSavePostDetail(nextapp);
								break;
							case AsyncMissionNextAppType. Post_List:
								ProcessSavePostList(nextapp);
								break;
							case AsyncMissionNextAppType. Comment_List:
								ProcessSaveCommentList(nextapp);
								break;
						}
					}
				};
			client. DownloadStringAsync(new Uri(mission. queryStringWithUrl, UriKind. Absolute));
		}

		private void ProcessSavePostDetail( XElement root)
		{
			if ( root == null )
			{
				return;
			}
			root = root. Element("post");
			Post post = new Post
			{
				id = root. Element("id"). Value. ToInt32( ),
				catalog = root. Element("catalog"). Value. Split(',') != null ? root. Element("catalog"). Value. Split(','). Select(c => c. ToInt32( )). ToArray( ) : null,
				title = root. Element("title"). Value,
				url = root. Element("url"). Value,
				body = root. Element("body"). Value,
				tags = root. Element("tags"). Value. Split(','),
				author = root. Element("author"). Value,
				pubDate = root. Element("pubDate"). Value,
				commentCount = root. Element("commentCount"). Value. ToInt32( ),
				relativePosts = root. Element("relativePosts") == null ?
										null :
										root. Element("relativePosts"). Elements("relativePost"). Select(
										r => new RelativePost
										{
											id = r. Element("id"). Value. ToInt32( ),
											author = r. Element("author"). Value,
											pubDate = r. Element("pubDate"). Value,
											title = r. Element("title"). Value,
										}
									). ToArray( ),
				//上一篇 下一篇文章ID 的获取
				previous = root. Element("previous") == null ? 0 : root. Element("previous"). Value. ToInt32( ),
				next = root. Element("next") == null ? 0 : root. Element("next"). Value. ToInt32( ),
			};
			//存储
			this. SavePostDetailToCache(post);
		}

		private void ProcessSavePostList(XElement root)
		{
			if ( root == null )
			{
				return;
			}
			PostList postList = new PostList
			{
				catalog = root. Element("catalog"). Value. ToInt32( ),
				postCount = root. Element("postCount"). Value. ToInt32( ),
				posts = root. Element("posts") == null ?
					null :
					root. Element("posts"). Elements("post"). Select(
					p => new Post
					{
						id = p. Element("id"). Value. ToInt32( ),
						title = p. Element("title"). Value,
						outline = p. Element("outline"). Value,
						commentCount = p. Element("commentCount"). Value. ToInt32( ),
						authorId = p. Element("authorId"). Value. ToInt32( ),
						author = p. Element("author"). Value,
						catalog = p. Element("catalog"). Value. Split(','). Select(c => c. ToInt32( )). ToArray( ),
						pubDate = p. Element("pubDate"). Value,
						img = p. Element("img") == null ? null : p. Element("img"). Value,
					}
				). ToArray( ),
			};
			//存储
			this. SavePostListToCache(postList. posts);
		}

		private void ProcessSaveCommentList(XElement root)
		{
			if ( root == null )
			{
				return;
			}
			CommentsList comments = new CommentsList
			{
				commentCount = root. Element("commentCount"). Value. ToInt32( ),
				comments = root. Element("comments") == null ?
									null :
									root. Element("comments"). Elements("comment"). Select(
				c => new Comment
				{
					id = c. Element("id"). Value. ToInt32( ),
					post = c. Element("post"). Value. ToInt32( ),
					name = c. Element("name"). Value,
					email = c. Element("email"). Value,
					url = c. Element("url"). Value,
					body = c. Element("body"). Value,
					pubDate = c. Element("pubDate"). Value,
				}). ToArray( ),
			};
			//存储
			this. SaveCommentsToCache(comments. comments);
		}
	}
}
